package com.example.demo.resources;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import com.example.demo.config.AbilityGateway;
import com.example.demo.config.AbilityOperation;
import com.example.demo.utils.JsonUtils;
import com.example.demo.utils.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.*;

import static cn.hutool.core.date.DatePattern.PURE_DATETIME_FORMAT;

@RestController
@RequestMapping("/base")
public class BaseResources {
    private static final Logger logger = LoggerFactory.getLogger(BaseResources.class);

    private final AbilityOperation abilityOperation;

    private final AbilityGateway abilityGateway;

    private final RestTemplate restTemplate;

    public BaseResources(AbilityOperation abilityOperation, AbilityGateway abilityGateway, RestTemplate restTemplate) {
        this.abilityOperation = abilityOperation;
        this.abilityGateway = abilityGateway;
        this.restTemplate = restTemplate;
    }

    @RequestMapping(value = "account", method = RequestMethod.POST)
    public Map<String, Object> account(@RequestBody Map<String, String> param) throws Exception {
        return result(param.get("name"));
    }


    private Map<String, Object> result(String name) throws Exception {
        String accessToken = getAccessToken();
        String dynamicToken = getDynamicToken();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        String format = DateUtil.format(new Date(), PURE_DATETIME_FORMAT);
        Map<String, Object> params = new LinkedHashMap<>();
        Map<String, Object> reqParam = new LinkedHashMap<>();
        Map<String, Object> busiInfo = new LinkedHashMap<>();
        Map<String, Object> head = new LinkedHashMap<>();
        head.put("method", "M_ABILITY_UNIUSER_100000191");
        head.put("format", "json");
        head.put("appId", abilityGateway.getAppid());
        head.put("openId", "111");
        head.put("operId", "111");
        head.put("version", "V1.0");
        head.put("accessToken", accessToken);
        head.put("sign", "SHA");
        head.put("timestamp", format);
        busiInfo.put("url_param", head);
        busiInfo.put("clientId", "uni_574_gs_rms");
//        busiInfo.put("clientId", "hrmsConfidentialWeb");
//        busiInfo.put("staffName", name);
        busiInfo.put("staffCode", name);
        busiInfo.put("pageSize", 10);
//        busiInfo.put("clientSecret", "confidentialWeb%hrms$SixLou=");
        busiInfo.put("clientSecret", "U2FsdGVkX18TCsMyohE8nk28WCoEhzv8jiXHW2Zazzw=");
        busiInfo.put("currentPage", 1);

        reqParam.put("BUSI_INFO", busiInfo);
        reqParam.put("PUB_INFO", new HashMap<String, Object>() {{
            put("OP_CODE", "***");
            put("CHANNEL_ID", "***");
            put("OP_ORG_ID", "***");
            put("REQ_TIME", format);
            put("REQ_SERIAL_NO", IdUtil.fastSimpleUUID());

        }});
        reqParam.put("PAGE_INFO", new HashMap<>(0));
        params.put("REQ_PARAM", reqParam);
        logger.debug("request:{}", JsonUtils.obj2StringPretty(params));
        String url = abilityOperation.getUrl() + "/oppf?timestamp=" + format + "&flowid=" + System.currentTimeMillis() + "&appId=" + abilityOperation.getAppid() + "&accessToken=" + dynamicToken + "&method=GANS_UNOQ_T_baseUserInfoQuery&format=json";
        String encodedValue = SecurityUtils.encodeAES256HexUpper(JsonUtils.obj2String(params), SecurityUtils.decodeHexUpper(abilityOperation.getAccessToken()));
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, new HttpEntity<>(encodedValue, headers), String.class);
        String decodeValue = SecurityUtils.decodeAES256HexUpper(Objects.requireNonNull(responseEntity.getBody()), SecurityUtils.decodeHexUpper(abilityOperation.getAccessToken()));
        Map<String, Object> entries = JSONUtil.parseObj(decodeValue);
        logger.debug("decodeValue:{}", JsonUtils.obj2StringPretty(entries));
        return entries;
    }

    private String getDynamicToken() {
        Map<String, String> params = new HashMap<>(3);
        params.put("appId", abilityOperation.getAppid());
        params.put("accessToken", abilityOperation.getAccessToken());
        params.put("Flag", "opcf");

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(
                abilityOperation.getUrl() + "/opcfapi/V1/partner/ability/dynamicToken",
                new HttpEntity<>(JsonUtils.obj2String(params), headers),
                String.class);
        Map<String, Object> result = JSONUtil.parseObj(responseEntity.getBody());
        return result.getOrDefault("dynamicToken", "没有值").toString();
    }

    private String getAccessToken() throws Exception {
        String dynamicToken = getDynamicToken();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        String format = DateUtil.format(new Date(), PURE_DATETIME_FORMAT);
        Map<String, Object> params = new LinkedHashMap<>();
        Map<String, Object> reqParam = new LinkedHashMap<>();
        Map<String, Object> busiInfo = new LinkedHashMap<>();
        busiInfo.put("grant_type", "client_credentials");
        busiInfo.put("app_id", abilityGateway.getAppid());
        busiInfo.put("app_key", abilityGateway.getAppKey());
        params.put("REQ_PARAM", reqParam);
        reqParam.put("BUSI_INFO", busiInfo);
        reqParam.put("PUB_INFO", new HashMap<String, Object>() {{
            put("OP_CODE", "***");
            put("CHANNEL_ID", "***");
            put("OP_ORG_ID", "***");
            put("REQ_TIME", format);
            put("REQ_SERIAL_NO", IdUtil.fastSimpleUUID());

        }});
        reqParam.put("PAGE_INFO", new HashMap<>(0));
        String url = abilityOperation.getUrl() + "/oppf?timestamp=" + format + "&flowid=" + System.currentTimeMillis() + "&appId=" + abilityOperation.getAppid() + "&accessToken=" + dynamicToken + "&method=GANS_UNOT_T_oauthToken&format=json";
        String encodedValue = SecurityUtils.encodeAES256HexUpper(JsonUtils.obj2String(params), SecurityUtils.decodeHexUpper(abilityOperation.getAccessToken()));
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, new HttpEntity<>(encodedValue, headers), String.class);
        String decodeValue = SecurityUtils.decodeAES256HexUpper(Objects.requireNonNull(responseEntity.getBody()), SecurityUtils.decodeHexUpper(abilityOperation.getAccessToken()));
        Map<String, Object> result = JSONUtil.parseObj(decodeValue);
        Map<String, Object> rspParam = (Map<String, Object>) result.get("RSP_PARAM");
        Map<String, Object> rspBusiInfo = (Map<String, Object>) rspParam.get("BUSI_INFO");
        return rspBusiInfo.get("access_token").toString();
    }
}
